package cn.org.dian.easycommunicate;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import cn.org.dian.easycommunicate.util.GoogleTranslateService;
import cn.org.dian.easycommunicate.util.NetworkTrafficStats;
import cn.org.dian.easycommunicate.util.Utilities;

import com.google.api.translate.Language;

public class OnlineTranslateActivity extends TTSActivity implements
        OnItemSelectedListener, OnClickListener {

    private static final int VOICE_RECOGNITION_REQUEST_CODE = 1;
    // private static final String TAG = "OnlineTranslateActivity";

    /**
     * map to online_search_languages string array in strings.xml map to
     * fromSpinner and toSpinner
     */
    private static ArrayList<Language> languageIndexMapper;

    static {
        languageIndexMapper = new ArrayList<Language>();
        languageIndexMapper.add(Language.CHINESE_SIMPLIFIED);
        languageIndexMapper.add(Language.CHINESE_TRADITIONAL);
        languageIndexMapper.add(Language.ENGLISH);
        languageIndexMapper.add(Language.FRENCH);
        languageIndexMapper.add(Language.GERMAN);
        languageIndexMapper.add(Language.ITALIAN);
        languageIndexMapper.add(Language.SPANISH);
        languageIndexMapper.add(Language.JAPANESE);
        languageIndexMapper.add(Language.KOREAN);
    }

    private int fromSpinnerPosition;
    private int toSpinnerPosition;

    private int voiceRecoResultPickIndex;
    private ArrayList<String> voiceRecoResultList = null;

    private EditText onlineSearchInput = null;
    private EditText onlineSearchResult = null;
    private Button buttonVoiceInput = null;
    private boolean voiceInputAvailability = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.online_translate_activity);

        // init spinners
        ArrayAdapter<String> fromLanguageAdapter = new ArrayAdapter<String>(
                this, android.R.layout.simple_spinner_item, getResources()
                        .getStringArray(R.array.online_search_languages));
        fromLanguageAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        Spinner fromLanguageSpinner = (Spinner) findViewById(R.id.from_language_select_spinner);
        fromLanguageSpinner.setAdapter(fromLanguageAdapter);
        fromLanguageSpinner.setOnItemSelectedListener(this);
        

        ArrayAdapter<String> toLanguageAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, getResources()
                        .getStringArray(R.array.online_search_languages));
        toLanguageAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        Spinner toLanguageSpinner = (Spinner) findViewById(R.id.to_language_select_spinner);
        toLanguageSpinner.setAdapter(toLanguageAdapter);
        toLanguageSpinner.setOnItemSelectedListener(this);
        
        boolean isEng = Utilities.isCurrentLanEng();
        fromLanguageSpinner.setSelection(isEng ? 2 : 0);// default
        toLanguageSpinner.setSelection(isEng ? 0 : 2); // default

        // init edit text
        onlineSearchInput = (EditText) findViewById(R.id.online_search_input);
        onlineSearchResult = (EditText) findViewById(R.id.online_search_result);

        // init buttons
        findViewById(R.id.online_search_button).setOnClickListener(this);
        findViewById(R.id.from_lang_speak_button).setOnClickListener(this);
        findViewById(R.id.to_lang_speak_button).setOnClickListener(this);

        buttonVoiceInput = (Button) findViewById(R.id.voice_input_button);
        // check voice input usability and init voice input button
        if (!checkVoiceInputUsability()) {
            // if not support, hide the button
            buttonVoiceInput.setVisibility(View.INVISIBLE);
            voiceInputAvailability = false;
        } else {
            buttonVoiceInput.setOnClickListener(this);
            voiceInputAvailability = true;
        }
    }

    @Override
	protected void onResume() {
		
		super.onResume();
		// check network
        if (!Utilities.checkNetworkUsability()) {
            Utilities.showLongToast(this, R.string.network_error);
        }
	}

	/**
     * Handle the results from the recognition activity.
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == VOICE_RECOGNITION_REQUEST_CODE) {
            // traffic stats end
            NetworkTrafficStats.endTrafficStats(true);
            if (resultCode == RESULT_OK) {
                // Fill the list view with the strings the recognizer thought it
                // could have heard
                voiceRecoResultList = data
                        .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                ArrayAdapter<String> matchesAdapter = new ArrayAdapter<String>(
                        this, R.layout.custom_list_item_single_choice,
                        voiceRecoResultList);

                // show a dialog to allow user choose from the results
                String alertMessage = getResources().getString(
                        R.string.voice_reco_result_choose_msg);
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(alertMessage)
                        .setPositiveButton(R.string.confirm,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        onlineSearchInput.setText(voiceRecoResultList
                                                .get(voiceRecoResultPickIndex));
                                        voiceRecoResultPickIndex = 0;
                                    }
                                })
                        .setNegativeButton(R.string.cancel,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        voiceRecoResultPickIndex = 0;
                                        dialog.cancel();
                                    }
                                })
                        .setSingleChoiceItems(matchesAdapter, 0,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        voiceRecoResultPickIndex = which;
                                    }
                                })
                        .setNeutralButton(R.string.speak_again,
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog,
                                            int which) {
                                        voiceRecoResultPickIndex = 0;
                                        requestVoiceReco();
                                    }
                                });
                AlertDialog alertDialog = builder.create();
                alertDialog.show();

            } else {
                Utilities.showLongToast(getContext(), R.string.voice_reco_fail);
            }
        }
        // for TTSActivity
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position,
            long id) {
        if (parent.getId() == R.id.from_language_select_spinner) {
            this.fromSpinnerPosition = position;
            // enable or disable voice input button
            if (null != getExtraLanguage() && voiceInputAvailability) {
            	this.buttonVoiceInput.setVisibility(View.VISIBLE);
            } else {
                this.buttonVoiceInput.setVisibility(View.INVISIBLE);
            }
        } else if (parent.getId() == R.id.to_language_select_spinner) {
            this.toSpinnerPosition = position;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }

    @Override
    public void onClick(View v) {

        if (v.getId() == R.id.online_search_button) {
            if (!Utilities.checkNetworkUsability()) {
                Utilities.showLongToast(this, R.string.network_error);
                return;
            }
            if (verifyEmptyEditText(onlineSearchInput)) {
                String query = onlineSearchInput.getText().toString().trim();
                new AsyncTranslateTask().execute(query,
                        languageIndexMapper.get(this.fromSpinnerPosition),
                        languageIndexMapper.get(this.toSpinnerPosition));
            }
        } else if (v.getId() == R.id.from_lang_speak_button) {
            if (verifyEmptyEditText(onlineSearchInput)) {
                String speakText = onlineSearchInput.getText().toString()
                        .trim();
                Language language = languageIndexMapper
                        .get(this.fromSpinnerPosition);
                asyncSpeak(language, speakText);
            }
        } else if (v.getId() == R.id.to_lang_speak_button) {
            if (verifyEmptyEditText(onlineSearchResult)) {
                String speakText = onlineSearchResult.getText().toString()
                        .trim();
                Language language = languageIndexMapper
                        .get(this.toSpinnerPosition);
                asyncSpeak(language, speakText);
            }
        } else if (v.getId() == R.id.voice_input_button) {
            if (Utilities.checkNetworkUsability()) {
                requestVoiceReco();
            } else {
                Utilities.showLongToast(this, R.string.voice_reco_fail);
            }
        }

    }

    private void requestVoiceReco() {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getResources()
                .getString(R.string.voice_input_prompt));
        String extraLanguage = getExtraLanguage();
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, extraLanguage);
        // traffic stats
        NetworkTrafficStats.beginTrafficStats(true);
        startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
    }

    /**
     * if editText has nothing or just white space, an alert dialog with
     * alertMessage will appear.
     * 
     * @param editText
     * @return true if no empty
     */
    private boolean verifyEmptyEditText(EditText editText) {
        if (!"".equals(editText.getText().toString().trim())) {
            return true;
        }
        String alertMessage = getResources().getString(
                R.string.empty_alert_text);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(alertMessage).setPositiveButton(R.string.confirm,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }

                });
        AlertDialog alertDialog = builder.create();
        alertDialog.show();
        return false;
    }

    /**
     * Check to see if a recognition activity is present
     * 
     * @return
     */
    private boolean checkVoiceInputUsability() {
        PackageManager pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(
                RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
        if (activities.size() != 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * map from language index to correspond string
     * 
     * @return string parameter for RecognizerIntent.EXTRA_LANGUAGE, like
     *         "zh-CN" or "en-US" <br>
     *         null if not currently supported.
     */
    private String getExtraLanguage() {
        Language language = languageIndexMapper.get(fromSpinnerPosition);
        if (language.equals(Language.CHINESE_SIMPLIFIED)) {
            return "zh-CN";
        } else if (language.equals(Language.ENGLISH)) {
            return "en-US";
        } else {
            return null; // not currently support
        }
    }

    private Context getContext() {
        return this;
    }

    /**
     * input String query, Language from, Language to
     * 
     * @author LiuGen
     * @date 2011-5-9
     */
    class AsyncTranslateTask extends AsyncTask<Object, Void, String> {

        @Override
        protected String doInBackground(Object... params) {
            try {
                // mobile network traffic stats
                NetworkTrafficStats.beginTrafficStats(false);
                return GoogleTranslateService.translate((String) params[0],
                        (Language) params[1], (Language) params[2]);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                NetworkTrafficStats.endTrafficStats(false);
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            getParent().setProgressBarIndeterminateVisibility(false);
            if (null != result) {
                ((TextView) findViewById(R.id.online_search_result))
                        .setText(result);
            } else {
                Utilities.showShortToast(getContext(),
                        R.string.remote_service_error);
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            getParent().setProgressBarIndeterminateVisibility(true);
            Utilities.showShortToast(getContext(), R.string.translate_prepare);
        }
    }

    @Override
    public void onBackPressed() {
        Activity parent = getParent();
        if (null != parent) {
            parent.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }


}
